package cn.iocoder.yudao.module.trade.statistics.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.iocoder.yudao.framework.business.basic.enums.TimeRangeTypeEnum;
import cn.iocoder.yudao.framework.business.basic.pojo.bo.DataComparison;
import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
import cn.iocoder.yudao.module.api.trade.statistics.dto.TradeOrderAreaStatisticsRespDTO;
import cn.iocoder.yudao.module.trade.statistics.bo.TradeOrderAreaStatisticsRespBO;
import cn.iocoder.yudao.module.trade.statistics.bo.TradeOrderMemberRankingRespBO;
import cn.iocoder.yudao.module.trade.statistics.bo.TradeOrderProductRankingRespBO;
import cn.iocoder.yudao.module.trade.statistics.bo.TradeOrderSummaryRespBO;
import cn.iocoder.yudao.module.trade.statistics.convert.TradeStatisticsConvert;
import cn.iocoder.yudao.module.trade.statistics.dal.mysql.TradeOrderStatisticsMapper;
import cn.iocoder.yudao.module.trade.statistics.vo.TradeOrderSummaryRespVO;
import cn.iocoder.yudao.module.trade.statistics.vo.TradeOrderTrendReqVO;
import cn.iocoder.yudao.module.trade.statistics.vo.TradeOrderTrendRespVO;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * 交易订单统计 Service 实现类
 *
 * @author owen
 */
@Service
@Validated
public class TradeOrderStatisticsServiceImpl implements TradeOrderStatisticsService {

    @Resource
    private TradeOrderStatisticsMapper tradeOrderStatisticsMapper;

    @Override
    public TradeOrderSummaryRespBO getOrderSummary(LocalDateTime beginTime, LocalDateTime endTime) {
        TradeOrderSummaryRespBO respBO = new TradeOrderSummaryRespBO();
        respBO.setOrderCreateCount(tradeOrderStatisticsMapper.selectCountByCreateTimeBetween(beginTime, endTime));
        respBO.setOrderPayCount(tradeOrderStatisticsMapper.selectCountByPayTimeBetween(beginTime, endTime));
        respBO.setOrderPayPrice(tradeOrderStatisticsMapper.selectSummaryPriceByPayTimeBetween(beginTime, endTime));
        return respBO;
    }

    @Override
    public List<TradeOrderAreaStatisticsRespDTO> getSummaryListByGroupAreaId() {
        List<TradeOrderAreaStatisticsRespBO> bos = tradeOrderStatisticsMapper.selectSummaryListGroupByAreaId();
        return TradeStatisticsConvert.INSTANCE.convertList3(bos);
    }

    @Override
    public Integer getOrderUserCount(LocalDateTime beginTime, LocalDateTime endTime) {
        return tradeOrderStatisticsMapper.selectUserCountByCreateTimeBetween(beginTime, endTime);
    }

    @Override
    public Integer getPayUserCount(LocalDateTime beginTime, LocalDateTime endTime) {
        return tradeOrderStatisticsMapper.selectUserCountByPayTimeBetween(beginTime, endTime);
    }

    @Override
    public Integer getOrderPayPrice(LocalDateTime beginTime, LocalDateTime endTime) {
        return tradeOrderStatisticsMapper.selectSummaryPriceByPayTimeBetween(beginTime, endTime);
    }

    @Override
    public Long getCountByStatusAndDeliveryType(Integer status, Integer deliveryType) {
        return tradeOrderStatisticsMapper.selectCountByStatusAndDeliveryType(status, deliveryType);
    }

    @Override
    public DataComparison<TradeOrderSummaryRespVO> getOrderComparison() {
        DataComparison<TradeOrderSummaryRespVO> comparison = new DataComparison<>();
        comparison.setValue(getPayPriceSummary(LocalDateTime.now()));
        comparison.setReference(getPayPriceSummary(LocalDateTime.now().minusDays(1)));
        return comparison;
    }

    private TradeOrderSummaryRespVO getPayPriceSummary(LocalDateTime date) {
        LocalDateTime beginTime = LocalDateTimeUtil.beginOfDay(date);
        LocalDateTime endTime = LocalDateTimeUtil.endOfDay(date);
        return tradeOrderStatisticsMapper.selectPaySummaryByPayStatusAndPayTimeBetween(
                Boolean.TRUE, beginTime, endTime);
    }

    @Override
    public List<DataComparison<TradeOrderTrendRespVO>> getOrderCountTrendComparison(TradeOrderTrendReqVO reqVO) {
        // 查询当前数据
        List<TradeOrderTrendRespVO> value = getOrderCountTrend(reqVO.getType(), reqVO.getBeginTime(), reqVO.getEndTime());
        // 查询对照数据
        LocalDateTime referenceEndTime = reqVO.getBeginTime().minusDays(1);
        LocalDateTime referenceBeginTime = referenceEndTime.minus(Duration.between(reqVO.getBeginTime(), reqVO.getEndTime()));
        List<TradeOrderTrendRespVO> reference = getOrderCountTrend(reqVO.getType(), referenceBeginTime, referenceEndTime);
        // 顺序对比返回
        return IntStream.range(0, value.size())
                .mapToObj(index -> {
                    DataComparison<TradeOrderTrendRespVO> comparison = new DataComparison<>();
                    comparison.setValue(CollUtil.get(value, index));
                    comparison.setReference(CollUtil.get(reference, index));
                    return comparison;
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<TradeOrderProductRankingRespBO> getOrderProductRanking(Integer limit) {
        if (limit == null || limit <= 0) {
            limit = 15;
        }
        List<TradeOrderProductRankingRespBO> list = tradeOrderStatisticsMapper.selectOrderProductRanking(limit);
        if (CollUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        return list;
    }

    @DataPermission(enable = false) // 禁用数据权限，无需按蒂娜普编号来查询
    @Override
    public List<TradeOrderMemberRankingRespBO> getOrderMemberRanking(Integer limit) {
        if (limit == null || limit <= 0) {
            limit = 15;
        }
        List<TradeOrderMemberRankingRespBO> list = tradeOrderStatisticsMapper.selectOrderMemberRanking(limit);
        if (CollUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        return list;
    }

    private List<TradeOrderTrendRespVO> getOrderCountTrend(Integer timeRangeType, LocalDateTime beginTime, LocalDateTime endTime) {
        List<TradeOrderTrendRespVO> result;
        String dateFormat;
        // 情况一：按年统计时，以月份分组
        if (TimeRangeTypeEnum.YEAR.getValue().equals(timeRangeType)) {
            result = tradeOrderStatisticsMapper.selectListByPayTimeBetweenAndGroupByMonth(beginTime, endTime);
            dateFormat = "yyyy-MM";
        } else {
            // 情况二：其它以天分组（天、周、月）
            result = tradeOrderStatisticsMapper.selectListByPayTimeBetweenAndGroupByDay(beginTime, endTime);
            dateFormat = "yyyy-MM-dd";
        }
        if (CollUtil.isEmpty(result)) {
            result = new ArrayList<>();
        }
        // 补充不存在的日期
        return fillMissingDates(result, dateFormat, beginTime.toLocalDate(), endTime.toLocalDate());
    }

    private List<TradeOrderTrendRespVO> fillMissingDates(List<TradeOrderTrendRespVO> result, String dateFormat, LocalDate beginTime, LocalDate endTime) {
        // 创建一个包含所有需要日期的列表
        List<LocalDate> allDates = new ArrayList<>();
        for (LocalDate date = beginTime; !date.isAfter(endTime); date = date.plusDays(1)) {
            allDates.add(date);
        }
        // 将查询结果转换为Map，以便快速查找
        Map<String, TradeOrderTrendRespVO> resultMap = new HashMap<>();
        for (TradeOrderTrendRespVO vo : result) {
            resultMap.put(vo.getDate(), vo);
        }
        // 创建一个新的结果列表，包含所有日期
        List<TradeOrderTrendRespVO> filledResult = new ArrayList<>();
        for (LocalDate date : allDates) {
            String dateStr = LocalDateTimeUtil.format(date, dateFormat);
            TradeOrderTrendRespVO vo = resultMap.get(dateStr);
            if (vo == null) {
                vo = new TradeOrderTrendRespVO();
                vo.setDate(dateStr);
                vo.setOrderPayCount(0);
                vo.setOrderPayPrice(0);
            }
            filledResult.add(vo);
        }
        return filledResult;
    }

}
